package com.douqu.game.activity;

import com.alibaba.fastjson.JSONObject;
import com.douqu.game.activity.database.mapper.ServerMapper;
import com.douqu.game.activity.database.model.ServerModel;
import com.douqu.game.activity.entity.BattleServerInfo;
import com.douqu.game.activity.entity.MainServerInfo;
import com.douqu.game.activity.gui.MainFrame;
import com.douqu.game.activity.manager.ActivityCampManager;
import com.douqu.game.activity.manager.LoadManager;
import com.douqu.game.activity.server.SpringContext;
import com.douqu.game.activity.server.netty.NettyTCPServer;
import com.douqu.game.activity.server.rmi.RMIServer;
import com.douqu.game.core.factory.ConfigFactory;
import com.douqu.game.core.netty.NettyConnection;
import com.douqu.game.core.util.CoreUtils;
import com.douqu.game.core.util.LogUtils;

import javax.swing.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: Bean
 * @Description:
 * @Date: 2018-03-07 14:48
 */
public class GameServer {


    private MainFrame mainFrame;


    private List<BattleServerInfo> battleServerList = new CopyOnWriteArrayList<>();

    private List<MainServerInfo> mainServerList = new CopyOnWriteArrayList<>();

    private Map<Integer, ServerModel> serverMap = new ConcurrentHashMap<>();


    /**
     * 可缓存线程池，如果线程池长度超过处理需要，可灵活回收空闲线程，若无可回收，则新建线程
     */
    private ExecutorService service = Executors.newCachedThreadPool();


    private ActivityCampManager activityCampManager;

    private NettyTCPServer tcpServer;

    private RMIServer rmiServer;

    private boolean isRunning;

    private static GameServer instance = null;

    private GameServer()
    {
        activityCampManager = new ActivityCampManager();
    }

    public static GameServer getInstance()
    {
        if(instance == null)
            instance = new GameServer();

        return instance;
    }

//    public void initSpringConfig()
//    {
//        activityCampManager = new ActivityCampManager();
//
//        CommonConfig commonConfig = SpringContext.getBean(CommonConfig.class);
//
//        activityCampManager.setId(commonConfig.getCampActivityId());
//
//        String[] strs = commonConfig.getBattleServerPort().split(ConstantFactory.COMMA);
//        this.battleServerPorts = new int[strs.length];
//        for(int i = 0; i < strs.length; i++)
//        {
//            battleServerPorts[i] = Integer.parseInt(strs[i]);
//        }
//    }


    public void startThread(Runnable runnable)
    {
        service.execute(runnable);
    }

    public void start()
    {
        SpringServer.start();

        SpringContext.showConfig();

        LoadManager.load();

        loadServer();

        activityCampManager.load();

        if(tcpServer == null)
        {
//            startThread(()->{
                tcpServer = new NettyTCPServer();
                tcpServer.start();
//            });
        }
    }

    public void startRMI()
    {
        if(rmiServer == null)
        {
            rmiServer = new RMIServer();
            rmiServer.start();

            isRunning = true;
        }
    }

    public void loadServer()
    {
        ServerMapper serverMapper = SpringContext.getBean(ServerMapper.class);
        List<ServerModel> serverList = serverMapper.getCampActivityServerList(activityCampManager.getId());
        if(serverList == null || serverList.isEmpty())
        {
            LogUtils.error("获取服务器列表错误 -> id:" + activityCampManager.getId());
            JOptionPane.showMessageDialog(null, "活动ID错误，请检查 -> " + activityCampManager.getId());
            System.exit(0);
            return;
        }

        serverMap.clear();

        for(ServerModel serverModel : serverList)
        {
            serverMap.put(serverModel.getId(), serverModel);
        }
    }

    public void activityCampConnectMain()
    {
        ServerModel serverModel = null;
        for(Map.Entry<Integer, ServerModel> entry : serverMap.entrySet())
        {
            serverModel = entry.getValue();
            new MainServerInfo(serverModel.getId(), serverModel.getIp(), serverModel.getPort()).startTCP();
        }

    }





    public void stop()
    {
        service.shutdown();

        LogUtils.info("关闭活动服务器时，保存服务器数据开始<---------->");

        GameServer.getInstance().getActivityCampManager().save();

        LogUtils.info("关闭活动服务器时，保存服务器数据成功<---------->");

        if(tcpServer != null)
        {
            tcpServer.stop();
        }

        if(rmiServer != null)
        {
            rmiServer.stop();
        }

        SpringContext.stop();

        isRunning = false;

        LogUtils.error("所有参与活动的主服都已关闭，活动服也关闭 -> ID:" + activityCampManager.getId());

        System.exit(0);
    }

    public void startMatchTask()
    {

    }


    public void update()
    {

    }


    public void sendRankInfo(JSONObject jsonObject)
    {
        if(jsonObject == null || jsonObject.isEmpty())
            return;

        for(MainServerInfo serverInfo : mainServerList)
        {
            serverInfo.sendRankInfo(jsonObject);
        }
    }

    public void sendActivityStatus(boolean running, boolean sendFirstCampPlayer)
    {
        for(MainServerInfo serverInfo : mainServerList)
        {
            serverInfo.sendActivityStatus(running, sendFirstCampPlayer);
        }
    }

    public void sendToBattleServerLogConfig()
    {
        for(BattleServerInfo battleServerInfo : battleServerList)
        {
            battleServerInfo.sendLogLevel();
        }
    }

    public void sendToBattleServerUpdateConfig()
    {
        for(BattleServerInfo serverInfo : battleServerList)
        {
            serverInfo.sendUpdateConfig();
        }
    }

    public void sendActivityTime()
    {
        for(MainServerInfo serverInfo : mainServerList)
        {
            serverInfo.sendCampActivityTime();
        }
    }

    public void addBattleServerInfo(BattleServerInfo battleServerInfo)
    {
        if(getBattleServerInfo(battleServerInfo.getPort()) != null)
            return;

        battleServerList.add(battleServerInfo);
    }


    public int getFreeBattleServerPort()
    {
        for(int port : ConfigFactory.SERVER_PORT_BATTLE)
        {
            if(getBattleServerInfo(port) == null)
                return port;
        }
        return 0;
    }


    public BattleServerInfo getBattleServerInfo(int port)
    {
        for(BattleServerInfo serverInfo : battleServerList)
        {
            if(serverInfo.getPort() == port)
                return serverInfo;
        }
        return null;
    }

    public BattleServerInfo getFreeBattleServer()
    {
        if(battleServerList.isEmpty())
            return null;

        if(battleServerList.size() == 1)
            return battleServerList.get(0);

        BattleServerInfo result = Collections.min(battleServerList, new Comparator<BattleServerInfo>() {
            @Override
            public int compare(BattleServerInfo o1, BattleServerInfo o2) {

                return new Integer(o1.getBattleCount()).compareTo(o2.getBattleCount());
            }
        });

        LogUtils.info("获取空闲战斗服务器:" + result);

        return result;
    }

    public void removeBattleServer(NettyConnection connection)
    {
        for(BattleServerInfo battleServerInfo : battleServerList)
        {
            if(battleServerInfo.getConnection().getId() == connection.getId())
            {
                battleServerList.remove(battleServerInfo);
                break;
            }
        }
    }


    public void addMainServerInfo(MainServerInfo serverInfo)
    {
        mainServerList.add(serverInfo);
    }

    public MainServerInfo getMainServerInfo(String host, int port)
    {
        for(MainServerInfo serverInfo : mainServerList)
        {
            if(serverInfo.getHost().equals(host) && serverInfo.getPort() == port)
                return serverInfo;
        }
        return null;
    }

    public MainServerInfo getMainServerInfo(int id)
    {
        for(MainServerInfo serverInfo : mainServerList)
        {
            if(serverInfo.getId() == id)
                return serverInfo;
        }
        return null;
    }

    public void restartMainServer(int id, String host, int port)
    {
        new MainServerInfo(id, host, port).startTCP();
    }


    public void removeMainServerInfo(int id, boolean check)
    {

        for(MainServerInfo serverInfo : mainServerList)
        {
            if(serverInfo.getId() == id)
            {
                mainServerList.remove(serverInfo);
                break;
            }
        }

        if(check && mainServerList.isEmpty())
        {
            stop();
        }
    }
    public void removeMainServerInfo(MainServerInfo serverInfo)
    {
        mainServerList.remove(serverInfo);
    }

    public List<MainServerInfo> getMainServerList()
    {
        return mainServerList;
    }

    public ActivityCampManager getActivityCampManager() {
        return activityCampManager;
    }


    public String createBattleId(String playerIndex, String targetIndex)
    {
        return playerIndex.substring(0,4) + targetIndex.substring(0,targetIndex.length()>=4?4:targetIndex.length()) + CoreUtils.createUUID(6).toUpperCase();
    }

    public boolean isRunning() {
        return isRunning;
    }

    public MainFrame getMainFrame() {
        return mainFrame;
    }

    public void setMainFrame(MainFrame mainFrame) {
        this.mainFrame = mainFrame;
    }

    public boolean isHaveBattleServer()
    {
        return !battleServerList.isEmpty();
    }

    public String getServerNameRemark(int serverId)
    {
        ServerModel serverModel = serverMap.get(serverId);
        return serverModel == null ? "" : serverModel.getRemark();
    }

    public void reloadServerModel(ServerModel serverModel)
    {
        if(serverModel == null)
            return;

        LogUtils.warn("管理员修改了服务器信息 -> " + serverModel);

        serverMap.put(serverModel.getId(), serverModel);
    }


}
